package com.hr.classes.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hr.classes.entity.*;
import com.hr.classes.entity.base.TableListDTO;
import com.hr.classes.entity.dto.TbWorkRecordDTO;
import com.hr.classes.entity.dto.TbWorkRecordStatisticsDTO;
import com.hr.classes.entity.po.TbWorkRecordPO;
import com.hr.classes.entity.vo.TbWorkRecordStatisticsVO;
import com.hr.classes.entity.vo.TbWorkRecordVO;
import com.hr.classes.mapper.*;
import com.hr.classes.service.TbWorkRecordService;
import com.hr.common.retrun.R;
import com.hr.system.entity.SysUser;
import com.hr.system.mapper.SysUserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.Temporal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <pre>
 * 描述：TODO
 * </pre>
 *
 * @类名：com.hr.classes.service.impl.TbWorkRecordServiceImpl
 * @创建日期: 2024/5/7 21:23
 */
@Service
public class TbWorkRecordServiceImpl implements TbWorkRecordService {

    @Autowired
    private TbWorkRecordMapper tbWorkRecordMapper;

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private TbClassesUserMapper tbClassesUserMapper;
    @Autowired
    private TbClassesMapper tbClassesMapper;
    @Autowired
    private TbClassesRuleMapper tbClassesRuleMapper;
    @Autowired
    private TbAttendanceRuleMapper tbAttendanceRuleMapper;

    //查询记录
    @Override
    public TableListDTO<TbWorkRecordDTO> getList(TbWorkRecordVO tbWorkRecordVO) {
        Page<TbWorkRecordDTO> page = null;
        if (null != tbWorkRecordVO.getPageNum() && null != tbWorkRecordVO.getPageSize()) {
            page = new Page<>(tbWorkRecordVO.getPageNum(), tbWorkRecordVO.getPageSize());
            IPage<TbWorkRecordDTO> monthlyWorkRecordStatistics = tbWorkRecordMapper.listTbWorkRecord(page, tbWorkRecordVO.getEmpName(), tbWorkRecordVO.getWorkCode(), tbWorkRecordVO.getAffiliatedUnit());
            List<TbWorkRecordDTO> records = monthlyWorkRecordStatistics.getRecords();
            PageInfo<TbWorkRecordDTO> pageInfo = new PageInfo<>(records);
            pageInfo.setPageSize((int) monthlyWorkRecordStatistics.getSize());
            pageInfo.setPageNum((int) monthlyWorkRecordStatistics.getCurrent());
            pageInfo.setTotal(monthlyWorkRecordStatistics.getTotal());
            return TableListDTO.setPageData(pageInfo);
        } else {
            // 查全部
            List<TbWorkRecordDTO> monthlyWorkRecordStatistics = tbWorkRecordMapper.listTbWorkRecord(tbWorkRecordVO.getEmpName(), tbWorkRecordVO.getWorkCode(), tbWorkRecordVO.getAffiliatedUnit());
            PageInfo<TbWorkRecordDTO> pageInfo = new PageInfo<>(monthlyWorkRecordStatistics);
            pageInfo.setTotal(0);
            return TableListDTO.setPageData(pageInfo);
        }

    }



    @Override
    public Integer add(TbWorkRecordVO tbWorkRecordVO) {
        TbWorkRecord tbWorkRecord = new TbWorkRecord();
        BeanUtils.copyProperties(tbWorkRecordVO, tbWorkRecord);
        // 计算上班时长
        Date workUpRecord = tbWorkRecordVO.getWorkUpRecord();
        Date workDownRecord = tbWorkRecordVO.getWorkDownRecord();

        long between = DateUtil.between(workUpRecord, workDownRecord, DateUnit.HOUR);
        BigDecimal workTime = new BigDecimal(between).setScale(2, RoundingMode.HALF_UP);
        tbWorkRecord.setWorkTime(workTime);

        String normal = workTime.compareTo(new BigDecimal(10)) < 0 ? "异常" : "正常";
        tbWorkRecord.setNormal(normal);

        return tbWorkRecordMapper.insert(tbWorkRecord);
    }

    @Override
    public TbWorkRecordDTO get(Integer id) {
        TbWorkRecordDTO tbWorkRecordDTO = new TbWorkRecordDTO();
        TbWorkRecord tbWorkRecord = tbWorkRecordMapper.selectById(id);
        if (tbWorkRecord == null) {
            return tbWorkRecordDTO;
        }
        BeanUtils.copyProperties(tbWorkRecord, tbWorkRecordDTO);

        SysUser sysUser = sysUserMapper.selectById(tbWorkRecord.getUserId());
        if (sysUser != null) {
            tbWorkRecordDTO.setEmpName(sysUser.getEmpName());
        }
        return tbWorkRecordDTO;
    }

    @Override
    public Integer update(TbWorkRecordVO tbWorkRecordVO) {
        TbWorkRecord tbWorkRecord = new TbWorkRecord();
        BeanUtils.copyProperties(tbWorkRecordVO, tbWorkRecord);
        // 计算上班时长
        Date workUpRecord = tbWorkRecordVO.getWorkUpRecord();
        Date workDownRecord = tbWorkRecordVO.getWorkDownRecord();

        long between = DateUtil.between(workUpRecord, workDownRecord, DateUnit.HOUR);
        BigDecimal workTime = new BigDecimal(between).setScale(2, RoundingMode.HALF_UP);
        tbWorkRecord.setWorkTime(workTime);

        String normal = workTime.compareTo(new BigDecimal(10)) < 0 ? "异常" : "正常";
        tbWorkRecord.setNormal(normal);

        return tbWorkRecordMapper.updateById(tbWorkRecord);
    }

    @Override
    public Integer deletes(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return 0;
        }
        return tbWorkRecordMapper.deleteBatchIds(ids);
    }

    @Override
    public List<TbWorkRecordPO> getListPO(TbWorkRecordVO tbWorkRecordVO) {
        Wrapper queryWrapper = getQueryWrapper(tbWorkRecordVO);
        List<TbWorkRecord> tbWorkRecords = tbWorkRecordMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(tbWorkRecords)) {
            return new ArrayList<>();
        }

        List<Integer> userIds = tbWorkRecords.stream().map(TbWorkRecord::getUserId).distinct().collect(Collectors.toList());
        List<SysUser> sysUsers = sysUserMapper.selectBatchIds(userIds);
        Map<Integer, String> userMap = sysUsers.stream().collect(HashMap::new, (m, v) -> m.put(v.getId(), v.getEmpName()), HashMap::putAll);

        List<TbWorkRecordPO> tbWorkRecordPOS = new ArrayList<>();
        TbWorkRecordPO tbWorkRecordPO = null;
        Integer index = 0;
        for (TbWorkRecord tbWorkRecord : tbWorkRecords) {
            index++;
            String empName = userMap.get(tbWorkRecord.getUserId());

            tbWorkRecordPO = new TbWorkRecordPO();
            tbWorkRecordPO.setSno(index.toString())
                    .setUserId(String.valueOf(tbWorkRecord.getUserId()))
                    .setEmpName(empName)
                    .setWorkUpRecord(DateUtil.format(tbWorkRecord.getWorkUpRecord(), "HH:mm:ss"))
                    .setWorkDownRecord(DateUtil.format(tbWorkRecord.getWorkDownRecord(), "HH:mm:ss"))
                    .setDate(DateUtil.format(tbWorkRecord.getDate(), "yyyy-MM-dd"))
                    .setWorkTime(tbWorkRecord.getWorkTime().setScale(2, RoundingMode.HALF_UP).toPlainString())
                    .setAffiliatedUnit(tbWorkRecord.getAffiliatedUnit())
                    .setNormal(tbWorkRecord.getNormal());
            tbWorkRecordPOS.add(tbWorkRecordPO);
        }

        return tbWorkRecordPOS;
    }

    private Wrapper getQueryWrapper(TbWorkRecordVO tbWorkRecordVO) {
        LambdaQueryWrapper<TbWorkRecord> queryWrapper = Wrappers.<TbWorkRecord>lambdaQuery();

        List<Integer> userIds = null;
        if (StringUtils.isNotBlank(tbWorkRecordVO.getEmpName())) {
            Map<String, Object> param = new HashMap<>();
            param.put("emp_name", tbWorkRecordVO.getEmpName());
            List<SysUser> sysUsers = sysUserMapper.selectByMap(param);
            userIds = sysUsers.stream().map(SysUser::getId).distinct().collect(Collectors.toList());

            queryWrapper.in(!CollectionUtils.isEmpty(userIds), TbWorkRecord::getUserId, userIds);
        }

        if (tbWorkRecordVO.getDate() != null) {
            String format = DateUtil.format(tbWorkRecordVO.getDate(), "yyyy-MM-dd");

            String begin = format + " 00:00:00";
            String end = format + " 23:59:59";

            queryWrapper.between(true, TbWorkRecord::getDate, begin, end);
        }
        return queryWrapper;
    }
    //统计
    @Override
    public TableListDTO<TbWorkRecordStatisticsVO> statistics(TbWorkRecordStatisticsDTO tbWorkRecordStatisticsDTO) {
        Page<TbWorkRecordStatisticsVO> page = null;
        if (null != tbWorkRecordStatisticsDTO.getPageNum() && null != tbWorkRecordStatisticsDTO.getPageSize()) {
            page = new Page<>(tbWorkRecordStatisticsDTO.getPageNum(), tbWorkRecordStatisticsDTO.getPageSize());
            IPage<TbWorkRecordStatisticsVO> monthlyWorkRecordStatistics = tbWorkRecordMapper.getMonthlyWorkRecordStatistics(page, tbWorkRecordStatisticsDTO.getEmpName(), tbWorkRecordStatisticsDTO.getWorkCode(),tbWorkRecordStatisticsDTO.getAffiliatedUnit(), tbWorkRecordStatisticsDTO.getBelongsMonth());
            List<TbWorkRecordStatisticsVO> records = monthlyWorkRecordStatistics.getRecords();
            buildEmpName(records);
            PageInfo<TbWorkRecordStatisticsVO> pageInfo = new PageInfo<>(records);
            pageInfo.setPageSize((int) monthlyWorkRecordStatistics.getSize());
            pageInfo.setPageNum((int) monthlyWorkRecordStatistics.getCurrent());
            pageInfo.setTotal(monthlyWorkRecordStatistics.getTotal());
            return TableListDTO.setPageData(pageInfo);
        } else {
            // 查全部
            List<TbWorkRecordStatisticsVO> monthlyWorkRecordStatistics = tbWorkRecordMapper.getMonthlyWorkRecordStatistics(tbWorkRecordStatisticsDTO.getEmpName(), tbWorkRecordStatisticsDTO.getWorkCode(),tbWorkRecordStatisticsDTO.getAffiliatedUnit(), tbWorkRecordStatisticsDTO.getBelongsMonth());
            buildEmpName(monthlyWorkRecordStatistics);
            PageInfo<TbWorkRecordStatisticsVO> pageInfo = new PageInfo<>(monthlyWorkRecordStatistics);
            pageInfo.setTotal(0);
            return TableListDTO.setPageData(pageInfo);
        }
    }

    @Override
    public R inClockOK(TbWorkRecordDTO tbWorkRecordDTO) {
        //判断当前时间是否在打卡时间范围内
        TbClassesUser tbClassesUser = tbClassesUserMapper.selectOne(Wrappers.<TbClassesUser>lambdaQuery()
                .eq(TbClassesUser::getUserId,tbWorkRecordDTO.getUserId()));
        TbClasses tbClasses = tbClassesMapper.selectById(tbClassesUser.getClassesId());
        TbClassesRule tbClassesRule = tbClassesRuleMapper.selectOne(Wrappers.<TbClassesRule>lambdaQuery()
                .eq(TbClassesRule::getClassesId,tbClassesUser.getClassesId()));
        TbAttendanceRule tbAttendanceRule = tbAttendanceRuleMapper.selectById(tbClassesRule.getRuleId());

        if (LocalDateTime.now().isBefore(tbAttendanceRule.getClockStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime())||LocalDateTime.now().isAfter(LocalDateTime.ofInstant(tbAttendanceRule.getClockEndTime().toInstant(), ZoneId.systemDefault()))){
            return R.error("不在打卡时间范围内");
        }
        //判断是否已经有上午打卡记录
        TbWorkRecord tbWorkRecord = new TbWorkRecord();
        tbWorkRecord.setDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
        tbWorkRecord.setUserId(tbWorkRecordDTO.getUserId());
        List<TbWorkRecord> tbWorkRecords = tbWorkRecordMapper.selectList(Wrappers.<TbWorkRecord>lambdaQuery()
                .eq(TbWorkRecord::getDate, tbWorkRecord.getDate())
                .eq(TbWorkRecord::getUserId, tbWorkRecord.getUserId())
//                .eq(TbWorkRecord::getClockTag, 1)
        );

        if (tbWorkRecords.size() == 0){
            tbWorkRecord.setWorkUpRecord(Date.from(tbWorkRecordDTO.getClockRecord().atZone(ZoneId.systemDefault()).toInstant()));
            tbWorkRecord.setClockTime(LocalDateTime.now());
            tbWorkRecord.setDate(new Date());
            tbWorkRecord.setClockTag(1);
            tbWorkRecord.setNormal("正常");
            tbWorkRecordMapper.insert(tbWorkRecord);
            return R.ok("上班打卡成功");
        }
        else if(tbWorkRecords.size() == 1){//已经有上午打卡
            tbWorkRecord.setWorkDownRecord(Date.from(tbWorkRecordDTO.getClockRecord().atZone(ZoneId.systemDefault()).toInstant()));
            tbWorkRecord.setClockTime(LocalDateTime.now());
            tbWorkRecord.setClockTag(2);
            if(Duration.between( LocalDateTime.ofInstant(tbWorkRecords.get(0).getWorkUpRecord().toInstant(), ZoneId.systemDefault()), LocalDateTime.now()).toHours() < 8 ){
                tbWorkRecord.setNormal("异常");
//                tbWorkRecordMapper.insert(tbWorkRecord);

                tbWorkRecordMapper.update(tbWorkRecord,Wrappers.<TbWorkRecord>lambdaQuery()
                        .eq(TbWorkRecord::getDate,tbWorkRecord.getDate())
                        .eq(TbWorkRecord::getUserId,tbWorkRecord.getUserId())
                );
                return R.error("打卡异常，下班过早，请在稍后提交补卡");
            }
            tbWorkRecord.setNormal("正常");
            tbWorkRecordMapper.insert(tbWorkRecord);
            return R.ok("下班打卡成功");
        }


        return R.error("打卡失败");
    }

    @Override
    public R getTodayClockInfo(TbWorkRecordDTO tbWorkRecordDTO) {

//        tbWorkRecord.setDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");

        List<TbWorkRecord> tbWorkRecords = tbWorkRecordMapper.selectList(Wrappers.<TbWorkRecord>lambdaQuery()
                .eq(TbWorkRecord::getDate, dateFormat.format(date))
                .eq(TbWorkRecord::getUserId, tbWorkRecordDTO.getUserId())
//                .eq(TbWorkRecord::getClockTag, 1)
        );
        if (tbWorkRecords.size() < 1) {
            return R.error("无打卡记录");
        }
//        TbWorkRecordDTO res = new TbWorkRecordDTO();
//        if (tbWorkRecords.size()>0){
//            res.setUpClockRecord(tbWorkRecords.stream().filter(x->x.getClockTag()==1).collect(Collectors.toList()).get(0).getClockTime());
//        }if (tbWorkRecords.size()>1){
//            res.setUpClockRecord(tbWorkRecords.stream().filter(x->x.getClockTag()==2).collect(Collectors.toList()).get(0).getClockTime());
//        }

            return R.ok(tbWorkRecords.get(0));

    }

    private void buildEmpName(List<TbWorkRecordStatisticsVO> monthlyWorkRecordStatistics) {
        if (!CollectionUtils.isEmpty(monthlyWorkRecordStatistics)) {
            // 构建人员信息
            List<Integer> userIds = monthlyWorkRecordStatistics.stream().map(TbWorkRecordStatisticsVO::getUserId).distinct().collect(Collectors.toList());
            List<SysUser> sysUsers = sysUserMapper.selectBatchIds(userIds);
            Map<Integer, String> userMap = sysUsers.stream().collect(HashMap::new, (m, v) -> m.put(v.getId(), v.getEmpName()), HashMap::putAll);

            monthlyWorkRecordStatistics.forEach(item -> {
                String empName = userMap.get(item.getUserId());
                item.setEmpName(empName);
            });
        }
    }


}
